Skip to content

Java Bean

前端-后端:

  • 前端提交的参数一般是面向过程的基本类型,后端操作时需要注入到对象中

后端-数据库:

  • 关系数据库在企业级应用开发中占主导地位,而主要的后端程序开发语言都是面向对象的,关系与对象之间就需要进行双向转换

组件开发

public int create(String no, String name, int age) {
  int res = 0;

  Connection con = null;
  PreparedStatement pstmt = null;
  String sql = "insert into Student values (?, ?, ?)";
  con = ConnectionUtil.getConnection();
  if (o != null && con != null) {
    try {
      pstmt = con.prepareStatement(sql);
      pstmt.setString(1, no);
      pstmt.setString(2, name);
      pstmt.setInt(3, age);
      res = pstmt.executeUpdate();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      ConnectionUtil.closePstmt(pstmt);
      ConnectionUtil.closeConnection(con);
    }
  }

  return res;
}

JavaBean介绍

Java Bean是Java语言中一种标准化的普通Java 类,是Java开发中最基础、最常用的组件,专门用于封装数据(存储对象的属性),遵循统一的编码规范,方便程序调用、框架解析和数据传递。

一个标准的Java Bean必须遵守4个硬性规范,这也是它和普通Java类的核心区别:

  1. 公共无参构造方法:类必须提供public修饰的无参构造器(不写构造器时,Java 会默认生成)。

  2. 私有属性:所有成员变量用private修饰,禁止外部直接访问。

  3. 公共 getter/setter 方法:为私有属性提供publicgetXxx()(读取属性)和setXxx()(修改属性)方法,方法名严格遵循驼峰命名(如属性name,对应getName()/setName())。

  4. 可序列化:实现java.io.Serializable接口(用于对象持久化、网络传输,框架中必备)。

import java.io.Serializable;

// 1. 实现Serializable接口(可序列化)
public class User implements Serializable {
    // 2. 私有属性
    private Long id;
    private String username;
    private Integer age;

    // 3. 公共无参构造方法
    public User() {
    }

    // 4. 公共getter/setter方法
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    ...
}
  1. 封装性:隐藏内部属性,通过 getter/setter 控制属性的读写,保证数据安全。
  2. 通用性:遵循统一标准,所有 Java 框架(Spring、MyBatis、SpringBoot 等)都能自动识别、操作 Java Bean。
  3. 轻量化:无复杂业务逻辑,仅专注数据封装,不依赖任何框架。
  4. 可复用:一个 Java Bean 可以在项目中多处使用,传递统一格式的数据。
  1. 数据封装:封装业务实体数据(用户、商品、订单等),替代零散的变量。
  2. 数据传递:在方法、模块、前后端、数据库之间统一传递数据(比如 Controller 接收前端参数、DAO 层封装数据库查询结果)。
  3. 框架适配:Java 生态所有框架(Spring 依赖注入、MyBatis 结果映射、JSON 序列化)都基于 Java Bean 规范工作。
  4. 组件复用:可作为独立组件,在不同项目中复用。
  • POJO:简单的 Java 对象,只需要私有属性+getter/setter,不强制实现序列化、无参构造,范围更广。
  • Java Bean是特殊的 POJO,必须严格遵守全部规范,是符合工业标准的 POJO。

Getter&Setter

Getter&setter方法用于访问 JavaBean 的属性

java bean

xust.demo.stu.domain.Student
/**
 * 学号
 */
private String no;
public String getNo(){
    return no;
}

public void setNo(String newValue){
    no = newValue;
}
源代码
xust.demo.stu.domain.Student
package xust.demo.stu.domain;

/**
 * Class Student
 * 学生表
 * @author XUST
 * @version 1.0, 2023-04-20
 */
public class Student{


    /**
     * 学号
     */
    private String no;
    public String getNo(){
        return no;
    }

    public void setNo(String newValue){
        no = newValue;
    }
    /**
     * 姓名
     */
    private String name;
    public String getName(){
        return name;
    }

    public void setName(String newValue){
        name = newValue;
    }
    /**
     * 性别
     */
    private String gender;
    public String getGender(){
        return gender;
    }

    public void setGender(String newValue){
        gender = newValue;
    }
    /**
     * 年龄
     */
    private Integer age;
    public Integer getAge(){
        return age;
    }

    public void setAge(Integer newValue){
        age = newValue;
    }
    /**
     * 所在系
     */
    private String dept;
    public String getDept(){
        return dept;
    }

    public void setDept(String newValue){
        dept = newValue;
    }

    @Override
    public String toString() {
    return "{" + "\"no\": " + "\"" + no + "\"" + ", " + "\"name\": " + "\"" + name + "\"" + ", " + "\"gender\": " + "\"" + gender + "\"" + ", " + "\"age\": " + age + ", " + "\"dept\": " + "\"" + dept + "\"" +  "}";
    }
}

后端-数据库数据交换

后端与数据库通过JavaBean作为数据载体、JDBC作为数据库访问桥梁,实现规范、统一的数据交互。

  1. JavaBean封装与数据库表对应的实体数据,通过getter/setter管理属性。
  2. 通过JDBC建立数据库连接,执行增删改查SQL语句。
  3. 查询时,将数据库结果集封装为JavaBean对象供后端使用。
  4. 增删改时,从JavaBean中取出数据作为SQL参数写入数据库。
  5. 以JavaBean承载数据、JDBC完成通信,实现后端与数据库的数据交换。
flowchart TD subgraph S1 [后端应用] A[业务逻辑层]:::primary --> B[数据访问层 DAO]:::success B --> C[JavaBean 实体对象]:::warning end subgraph S2 [数据库访问] D[JDBC 驱动]:::info E[数据库连接]:::info F[SQL 执行]:::info G[结果集处理]:::info end subgraph S3 [数据库] H[关系型数据库] end %% 数据流向 - 查询操作 B -->|o1. 调用查询方法| D D -->|o2. 建立连接| E E -->|o3. 执行查询SQL| F F -->|o4. 执行语句| H H -->|o5. 返回结果集| G G -->|o6. 封装结果| C C -->|o7. 返回JavaBean对象| B B -->|o8. 返回数据| A %% 数据流向 - 增删改操作 A -->|i1. 传递JavaBean| B B -->|i2. 提取属性值| C C -->|i3. 生成SQL参数| D D -->|i4. 建立连接| E E -->|i5. 执行修改SQL| F F -->|i6. 执行语句| H H -->|i7. 返回操作结果| B B -->|i8. 返回操作状态| A class S3 warning
xust.demo.stu.domain.Student
/**
 * 学号
 */
private String no;
public String getNo(){
    return no;
}

public void setNo(String newValue){
    no = newValue;
}
源代码
xust.demo.stu.domain.Student
package xust.demo.stu.domain;

/**
 * Class Student
 * 学生表
 * @author XUST
 * @version 1.0, 2023-04-20
 */
public class Student{


    /**
     * 学号
     */
    private String no;
    public String getNo(){
        return no;
    }

    public void setNo(String newValue){
        no = newValue;
    }
    /**
     * 姓名
     */
    private String name;
    public String getName(){
        return name;
    }

    public void setName(String newValue){
        name = newValue;
    }
    /**
     * 性别
     */
    private String gender;
    public String getGender(){
        return gender;
    }

    public void setGender(String newValue){
        gender = newValue;
    }
    /**
     * 年龄
     */
    private Integer age;
    public Integer getAge(){
        return age;
    }

    public void setAge(Integer newValue){
        age = newValue;
    }
    /**
     * 所在系
     */
    private String dept;
    public String getDept(){
        return dept;
    }

    public void setDept(String newValue){
        dept = newValue;
    }

    @Override
    public String toString() {
    return "{" + "\"no\": " + "\"" + no + "\"" + ", " + "\"name\": " + "\"" + name + "\"" + ", " + "\"gender\": " + "\"" + gender + "\"" + ", " + "\"age\": " + age + ", " + "\"dept\": " + "\"" + dept + "\"" +  "}";
    }
}
xust.demo.stu.dao.StudentDaoImpl.java
public Result create(Student o) {
  Result res = new Result(false);

  Connection con = null;
  PreparedStatement stmt = null;
  String sql = "insert into Student values (?, ?, ?, ?, ?)";
  con = ConnectionUtil.getConnection();
  if (o != null && con != null) {
    try {
      stmt = con.prepareStatement(sql);
      toR(o, stmt);
      if(stmt.executeUpdate() > 0){
        res.code = 0;
      }
    } catch (Exception e) {
      res.message = e.getMessage();
      e.printStackTrace();
    } finally {
      ConnectionUtil.closePstmt(stmt);
      ConnectionUtil.closeConnection(con);
    }
  }

  return res;
}
源代码
xust.demo.stu.dao.StudentDaoImpl.java
package xust.demo.stu.dao;

import java.sql.*;
import java.util.ArrayList;
import xust.stu.Result;
import xust.stu.ConnectionUtil;
import xust.demo.stu.domain.Student;

public class StudentDaoImpl implements StudentDao{
  public Result init() {
    Result res = new Result(false);

    Connection con = null;
    Statement stmt = null;
    String sql = "create table Student(" +
      "no TEXT primary key," +
      "name TEXT not null," +
      "gender TEXT," +
      "age INTEGER," +
      "dept TEXT" +
      ");";

    con = ConnectionUtil.getConnection();
    if(con != null){
      try {
        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(String.format("select count(*) from sqlite_master where type = 'table' and Upper(name) = '%s'", "Student".toUpperCase()));
        while(rs.next()){
          int count = rs.getInt(1);

          if(count == 0 && stmt.executeUpdate(sql) > 0){
            res.code = 0;
          }          
        }
      } catch (Exception e) {
        e.printStackTrace();
        res.message = e.getMessage();
      } finally {
        ConnectionUtil.closeStmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }

  /**
   * 对象填充到关系
   */
  private void toR(Student o, PreparedStatement stmt) throws Exception{
    if(o != null && stmt != null){
      String no = o.getNo();
      if(no != null){
        stmt.setString(1, no);       
      }
      String name = o.getName();
      if(name != null){
        stmt.setString(2, name);       
      }
      String gender = o.getGender();
      if(gender != null){
        stmt.setString(3, gender);       
      }
      Integer age = o.getAge();
      if(age != null){
        stmt.setInt(4, age);       
      }
      String dept = o.getDept();
      if(dept != null){
        stmt.setString(5, dept);       
      }
    }
  }

  /**
   * 关系填充到对象
   */
  private Student toO(ResultSet rs) throws Exception{
    Student res = null;

    if(rs != null){
      res = new Student();
      res.setNo(rs.getString("no"));
      res.setName(rs.getString("name"));
      res.setGender(rs.getString("gender"));
      res.setAge(rs.getInt("age"));
      res.setDept(rs.getString("dept"));
    }

    return res;
  }

  public Result create(Student o) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "insert into Student values (?, ?, ?, ?, ?)";
    con = ConnectionUtil.getConnection();
    if (o != null && con != null) {
      try {
        stmt = con.prepareStatement(sql);
        toR(o, stmt);
        if(stmt.executeUpdate() > 0){
          res.code = 0;
        }
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }
    }

    return res;
  }

  public Result delete(String no) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "delete from Student where no = ?;";
    con = ConnectionUtil.getConnection();
    if(con != null){
      try {

        stmt = con.prepareStatement(sql);
        stmt.setString(1, no);
        res.code = 0;
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }

  public Result update(Student o) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "update Student set No = ?, Name = ?, Gender = ?, Age = ?, Dept = ? where no = ?";
    con = ConnectionUtil.getConnection();
    if (o != null && con != null) {
      try {

        stmt = con.prepareStatement(sql);
        toR(o, stmt);
        stmt.setString(6, o.getNo());
        if(stmt.executeUpdate() > 0){
          res.code = 0;
        }
      } catch (Exception e) {
        e.printStackTrace();
        res.message = e.getMessage();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }
    }

    return res;
  }

  public Result get(String no) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "select * from Student where no = ?";
    con = ConnectionUtil.getConnection();
    if(con != null){
      try {
        stmt = con.prepareStatement(sql);
        stmt.setString(1, no);
        ResultSet rs = stmt.executeQuery();
        Student last = null;
        while (rs.next()) {
          last = new Student();
          last.setNo(rs.getString("no"));
          last.setName(rs.getString("name"));
          last.setGender(rs.getString("gender"));
          last.setAge(rs.getInt("age"));
          last.setDept(rs.getString("dept"));
        }

        res.code = 0;
        res.data = last;
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }

  public Result getAll() {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "select * from Student";
    con = ConnectionUtil.getConnection();
    if(con != null){
      try {
        stmt = con.prepareStatement(sql);
        ResultSet rs = stmt.executeQuery();
        ArrayList<Student> data = new ArrayList<Student>();
        while (rs.next()) {
          Student last = toO(rs);
          data.add(last);
        }

        res.code = 0;
        res.data = data;
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }
}

前端-后端数据交换

前端与后端通过请求响应机制进行数据交互,JavaBean 作为数据载体在前后端之间传递业务数据,实现参数接收、数据封装与结果返回。

  1. 前端通过表单、AJAX或接口请求向后端提交参数(如用户名、密码等)。
  2. 后端接收请求参数,自动或手动封装到JavaBean对象中。
  3. 后端处理业务逻辑,使用JavaBean存储和传递数据。
  4. 处理完成后,后端将JavaBean数据以JSON、对象属性等形式返回前端。
  5. 前端通过页面渲染、EL表达式或JS解析展示数据,完成一次完整交互。

JSP 提供了三个动作标签专门操作 JavaBean:

  • <jsp:useBean>:创建或获取Bean对象
  • <jsp:setProperty>:给Bean属性赋值
  • <jsp:getProperty>:从Bean取值显示到页面
flowchart TD subgraph 前端 A[用户界面]:::info B[表单/AJAX请求]:::primary C[数据展示/渲染]:::info end subgraph 后端 D[控制器/Servlet]:::warning E[JavaBean 实体对象]:::danger F[业务逻辑处理]:::info end subgraph 数据传递 G[HTTP请求/响应]:::success H[参数解析]:::info I[数据序列化/反序列化]:::info end %% 数据流向 - 前端到后端 A -->|i1. 输入数据| B B -->|i2. 提交请求| G G -->|i3. 接收请求| D D -->|i4. 解析参数| H H -->|i5. 封装数据| E E -->|i8. 传递给业务逻辑| F F -->|o1. 处理业务| E E -->|o2. 封装结果| D D -->|o3. 生成响应| G G -->|o4. 接收响应| C C -->|o5. 展示数据| A %% JSP动作标签流程 D -->|i6. 使用useBean| E D -->|i7. 使用setProperty| E E -->|o6. 使用getProperty| C

JSP接收前端数据

  1. 先写一个标准JavaBean(实体类)User.java

    package edu.xust.example;
    import java.io.Serializable;
    
    public class User implements Serializable {
        private String username;
        private String password;
    
        public User() {}
    
        // getter & setter
        public String getUsername() { return username; }
        public void setUsername(String username) { this.username = username; }
    
        ...
    }
    
  2. 前端表单页面(数据采集)login.jsp

    1
    2
    3
    4
    5
    <form action="show.jsp" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <button type="submit">提交</button>
    </form>
    

    关键点

    表单 name 必须 和 JavaBean 属性名完全一致,才能自动注入。

  3. 后端接收并封装到JavaBean(自动注入)(show.jsp)

    <%@ page contentType="text/html;charset=UTF-8" %>
    <% request.setCharacterEncoding("UTF-8"); %>
    
    <!-- 1. 创建/获取 JavaBean -->
    <jsp:useBean id="user" class="edu.xust.example.User" scope="page"/>
    <!-- 2. 自动把请求参数注入 Bean -->
    <jsp:setProperty name="user" property="*"/>
    <!-- 3. 从 Bean 取出数据显示(前后端传递完成) -->
    用户名:<jsp:getProperty name="user" property="username"/><br>
    密码:<jsp:getProperty name="user" property="password"/>
    

    解释

    • property="*":自动匹配所有表单参数到 Bean 属性
    • 不用手动 request.getParameter(),JSP 自动封装
    • 数据从前端表单 → JavaBean → 前端页面,完成传递

Servlet接收前端数据

  1. Servlet中封装Bean(手动注入)

    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
    
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
    
        // 存入 request 域
        request.setAttribute("user", user);
    
        // 转发到 JSP
        request.getRequestDispatcher("info.jsp").forward(request, response);
    }
    

  2. JSP 页面取出并显示

    1
    2
    3
    <jsp:useBean id="user" class="com.example.User" scope="request"/>
    用户名:${user.username}<br>
    密码:${user.password}
    

    或 EL 表达式(最简单):

    ${user.username}
    ${user.password}
    


JSP中访问JavaBean基本语法

  1. 导入JavaBean类

    • <%@ page import="类名"%>
  2. 实例化JavaBean类

1
2
3
<jsp:useBean id="Name" 类型模式 scope="page|request|session|appliction">
//内容实例…
</jsp:useBean>

Id

  • 创建JavaBean对象实例的名称。

Scope

  • 创建JavaBean对象实例的作用域。
范围 描述
Page Bean 只能在使用页面时使用。
Request Bean 在用户对其发出请求时存在
Session Bean一直存在于会话中,直至其终止或被删除为止
Application Bean 在整个应用程序中均可使用

类型模式

  • 对象所属的类或类型

    • class="类名"

    • class="类名" type="类型名"

    • beanName="bean名字" type="类型名"

    • type="类型名"

flowchart TD A[收到请求]:::success --> B{在scope中找到bean对象?}:::warning B -- no --> C{class可被实例化?}:::warning C -- no --> D[异常]:::danger C -- yes --> E[id引用class对象]:::success E --> G[处理jsp:useBean元素内容]:::success B -- yes --> F{有无type?}:::warning F -- yes --> H[类型转换]:::info H --> I{转换成功?}:::warning I -- yes --> G I -- no --> J[异常]:::danger F -- no --> G G --> K[................]:::info

jsp:setProperty/jsp:setProperty

为指定JavaBean对象(bean)设置属性值。

<jsp:setProperty name="bean名称" 属性表达式/>

参数含义

  • Name

    • 指明JavaBean实例对象的名字
  • 设置具体的属性

    • Perperty="*":为已经创建的bean的所有属性设置或修改属性值

    • Peroperty="属性名":为指定的的属性设置或修改属性值

    • Property="属性值" param="参数名" :为指定属性设置或修改属性值

    • Property="属性名" value="字符串|<%=表达或%>:设置属性的属性值

获取JavaBean对象实例的属性值<jsp:getProperty name="对象名" property="属性名"/>

Input.jsp
  <form action="Cal.jsp" method="post">
    <table border="1">
      <caption>输入长方体的长、宽、高</caption>
      <tr>
        <td>长度</td>
        <td><input type="text" name="length" /></td>
      </tr>
      <tr>
        <td>宽度</td>
        <td><input type="text" name="width" /></td>
      </tr>
      <tr>
        <td>高度</td>
        <td><input type="text" name="height" /></td>
      </tr>
      <tr>
        <td><input type="submit" value="提交" /></td>
      </tr>
    </table>
  </form>
</body>

</html>

源代码
Input.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
  <!DOCTYPE html>
  <html>

  <head>
    <meta charset="utf-8">
    <title>Insert title here</title>
  </head>

  <body>
    <form action="Cal.jsp" method="post">
      <table border="1">
        <caption>输入长方体的长、宽、高</caption>
        <tr>
          <td>长度</td>
          <td><input type="text" name="length" /></td>
        </tr>
        <tr>
          <td>宽度</td>
          <td><input type="text" name="width" /></td>
        </tr>
        <tr>
          <td>高度</td>
          <td><input type="text" name="height" /></td>
        </tr>
        <tr>
          <td><input type="submit" value="提交" /></td>
        </tr>
      </table>
    </form>
  </body>

  </html>

BeanTest/BeanTest/src/main/webapp/Cal.jsp
  <jsp:useBean id="cuboid1" scope="page" class="beans.CuboidBean" />
  <jsp:setProperty name="cuboid1" property="*" />
  <%
  if (cuboid1.isCuboid()) {
    out.println("CuboidBean的应用一<br>");
    out.println("长=" + cuboid1.getLength());
    out.println("宽=" + cuboid1.getWidth());
    out.println("高=" + cuboid1.getHeight());
    out.println("周长:" + cuboid1.getPerimeter());
    out.println("面积:" + cuboid1.getArea());
    out.println("体积:" + cuboid1.getVolume());
  }
  %>

  <jsp:useBean id="cuboid2" scope="page" class="beans.CuboidBean">
    <jsp:setProperty name="cuboid2" property="width" value="23" />
    <jsp:setProperty name="cuboid2" property="height" />
    <jsp:setProperty name="cuboid2" property="length" />
  </jsp:useBean>
  <%
  if (cuboid2.isCuboid()) {
    out.println("<br><hr>CuboidBean的应用二<br>");
    out.println("长=" + cuboid2.getLength());
    out.println("宽=" + cuboid2.getWidth());
    out.println("高=" + cuboid2.getHeight());
  }
  %>

  <jsp:useBean id="cuboid3" scope="page" class="beans.CuboidBean">
    <jsp:setProperty name="cuboid3" property="width"
      value="<%=cuboid2.getHeight()%>" />
    <jsp:setProperty name="cuboid3" property="height"
      value="<%=cuboid2.getLength()%>" />
    <jsp:setProperty name="cuboid3" property="length"
      value="<%=cuboid2.getWidth()%>" />
  </jsp:useBean>
  <%
  if (cuboid3.isCuboid()) {
    out.println("<br><hr>CuboidBean的应用三->修改CuboidBean的长宽高<br>");
    out.println("长=" + cuboid3.getLength());
    out.println("宽=" + cuboid3.getWidth());
    out.println("高=" + cuboid3.getHeight());
  }
  %>
</body>

</html>

源代码
BeanTest/BeanTest/src/main/webapp/Cal.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
  pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<title>长方体计算</title>
</head>

<body>
  <jsp:useBean id="cuboid1" scope="page" class="beans.CuboidBean" />
  <jsp:setProperty name="cuboid1" property="*" />
  <%
  if (cuboid1.isCuboid()) {
    out.println("CuboidBean的应用一<br>");
    out.println("长=" + cuboid1.getLength());
    out.println("宽=" + cuboid1.getWidth());
    out.println("高=" + cuboid1.getHeight());
    out.println("周长:" + cuboid1.getPerimeter());
    out.println("面积:" + cuboid1.getArea());
    out.println("体积:" + cuboid1.getVolume());
  }
  %>

  <jsp:useBean id="cuboid2" scope="page" class="beans.CuboidBean">
    <jsp:setProperty name="cuboid2" property="width" value="23" />
    <jsp:setProperty name="cuboid2" property="height" />
    <jsp:setProperty name="cuboid2" property="length" />
  </jsp:useBean>
  <%
  if (cuboid2.isCuboid()) {
    out.println("<br><hr>CuboidBean的应用二<br>");
    out.println("长=" + cuboid2.getLength());
    out.println("宽=" + cuboid2.getWidth());
    out.println("高=" + cuboid2.getHeight());
  }
  %>

  <jsp:useBean id="cuboid3" scope="page" class="beans.CuboidBean">
    <jsp:setProperty name="cuboid3" property="width"
      value="<%=cuboid2.getHeight()%>" />
    <jsp:setProperty name="cuboid3" property="height"
      value="<%=cuboid2.getLength()%>" />
    <jsp:setProperty name="cuboid3" property="length"
      value="<%=cuboid2.getWidth()%>" />
  </jsp:useBean>
  <%
  if (cuboid3.isCuboid()) {
    out.println("<br><hr>CuboidBean的应用三->修改CuboidBean的长宽高<br>");
    out.println("长=" + cuboid3.getLength());
    out.println("宽=" + cuboid3.getWidth());
    out.println("高=" + cuboid3.getHeight());
  }
  %>
</body>

</html>

JavaBean属性

属性是JavaBean组件内部状态的抽象表示。

JavaBean属性分为四种类型:

  • Simple(简单)

  • Indexed(索引)

  • Bound(绑定)

  • Constrained(限制)


Simple属性

一个简单属性表示一个带有get/set方法的变量,语法如下:

1
2
3
public void set<PropertyName>(<PropertyType> value);
public <PropertyType> get<PropertyName>();
public boolean is<PropertyName>();

若同时具有get和set方法,则该属性可读可写;若只有一个方法,则该属性为只读或只写。

注意:在定义变量时用小写,如type,但在定义方法时第一个字母要大写,如getType(),setType()

PropertyTest/SimpleTest.java
public class SimpleTest {
  private String ourString="Hello"; //属性名为ourString,类型为字符串

  public String getOurString() {
    return ourString;
  }

  public void setOurString(String ourString) {
    this.ourString = ourString;
  }
}

Indexed属性

一个索引属性表示一个数组,同简单属性类似,可用get/set方法取得数组中的值,语法如下:

1
2
3
4
public void set<PropertyName>(int index, <PropertyType> value);
public <PropertyType> get<PropertyName>(int index);
public void set<PropertyName>(<PropertyType[]> value);
public <PropertyType[]> get<PropertyName>();
PropertyTest/IndexedTest.java
public class IndexedTest {
  private int[] dataSet = { 1, 2, 3, 4, 5, 6 };

  public IndexedTest() {
  }

  public void setDataSet(int[] x) {
    dataSet = x;
  }

  public void setDataSet(int index, int x) {
    dataSet[index] = x;
  }

  public int[] getDataSet() {
    return dataSet;
  }
}

Bound属性

一个Bound属性是指当该种属性的值发生变化时,通过PropertyChange事件通知其他的对象。

PropertyTest/BoundTest.java
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class BoundTest {
  String ourString = "Hello";
  private PropertyChangeSupport ourStringChanges = new PropertyChangeSupport(this);

  public void setString(String newString) {
    String oldString = new String();
    ourStringChanges.firePropertyChange(ourString, oldString, newString);
  }

  public String getString() {
    return ourString;
  }

  public void addOurStringChangeListener(PropertyChangeListener  l) {
    ourStringChanges.addPropertyChangeListener(l);
  }

  public void removeOurStringChangeListener(PropertyChangeListener l) {
    ourStringChanges.removePropertyChangeListener(l);
  }
}

Constrained属性

当这个属性的值要发生改变时,与这个属性建立了某种连接的其他java对象可否决属性值的改变。constrained属性的监听者通过抛出PropertyVectoEcxeption来阻止该属性的改变。

PropertyTest/ConstrainedTest.java
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;

public class ConstrainedTest {
  private PropertyChangeSupport changes = new PropertyChangeSupport(this);
  private VetoableChangeSupport vetos = new VetoableChangeSupport(this);

  private int ourPriceInCents;

  public void setPriceInCents(int newPriceInCents) throws PropertyVetoException {
    int oldPriceInCents = ourPriceInCents;
    vetos.fireVetoableChange("priceInCents", new Integer(oldPriceInCents), new Integer(newPriceInCents));
    ourPriceInCents = newPriceInCents;
    changes.firePropertyChange("priceInCents", new Integer(oldPriceInCents), new Integer(newPriceInCents));
  }

  public void addVetosChangeListener(VetoableChangeListener l) {
    vetos.addVetoableChangeListener(l);
  }

  public void removeVetoasChangeListener(VetoableChangeListener l) {
    vetos.removeVetoableChangeListener(l);
  }
}

封装数据存储逻辑

数据库访问流程

JDBC步骤


ORM

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。ORM框架是连接数据库的桥梁,只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。

ORM框架:为了解决面型对象与关系数据库存在的互不匹配的现象的框架。

当前ORM框架主要有五种:

  1. Hibernate 全自动 需要写hql语句

  2. iBATIS 半自动 自己写sql语句,可操作性强,小巧

  3. mybatis

  4. eclipseLink

  5. JFinal

ORM是对象关系映射的简称,主要任务是:

  1. 根据对象的类型生成表结构

  2. 将对象、列表操作,转换成SQL语句(或其他数据库的语句)

  3. 将SQL查询到的结果转换为对象、列表

对象模型 关系模型
类名对应 数据库中的表名
类属性对应  数据库里的字段
类实例对应 数据库表里的一行数据

优点:

  1. 提高开发效率,降低开发成本

  2. 使开发更加对象化

  3. 可移植

  4. 可以很方便地引入数据缓存之类的附加功能

缺点:

  1. 自动化进行关系数据库的映射需要消耗系统性能。其实这里的性能消耗还好啦,一般来说都可以忽略之。

  2. 在处理多表联查、where条件复杂之类的查询时,ORM的语法会变得复杂。


示例

DaoTest/Student.sql
1
2
3
4
5
6
7
create table Student(
    no TEXT primary key,
    name TEXT not null,
    gender TEXT,
    age INTEGER,
    dept TEXT
);
xust.demo.ConnectionUtil.java
/**
 * 创建连接
 * 
 * @return 连接对象
 */
public static Connection getConnection() {
  Connection res = null;

  try {
    Class.forName("org.sqlite.JDBC");
    res = DriverManager.getConnection("jdbc:sqlite:stu.db");
  } catch (Exception e) {
    System.err.println(e.getClass().getName() + ": " + e.getMessage());
    System.exit(0);
  }

  return res;
}
源代码
xust.demo.ConnectionUtil.java
package xust.demo;

import java.sql.*;

/**
 * 连接辅助类
 */
public class ConnectionUtil {
  /**
   * 创建连接
   * 
   * @return 连接对象
   */
  public static Connection getConnection() {
    Connection res = null;

    try {
      Class.forName("org.sqlite.JDBC");
      res = DriverManager.getConnection("jdbc:sqlite:stu.db");
    } catch (Exception e) {
      System.err.println(e.getClass().getName() + ": " + e.getMessage());
      System.exit(0);
    }

    return res;
  }

  /**
   * 关闭连接
   * 
   * @param connection 连接对象
   */
  public static void closeConnection(Connection connection) {
    if (connection != null) {
      try {
        connection.close();
      } catch (Exception e) {
        System.err.println(e.getClass().getName() + ": " + e.getMessage());
        System.exit(0);
      }
    }
  }

  /**
   * 关闭语句
   * 
   * @param pstmt 语句对象
   */
  public static void closePstmt(PreparedStatement pstmt) {
    if (pstmt != null) {
      try {
        pstmt.close();
      } catch (Exception e) {
        System.err.println(e.getClass().getName() + ": " + e.getMessage());
        System.exit(0);
      }
    }
  }

  /**
   * 关闭语句
   * 
   * @param pstmt 语句对象
   */
  public static void closeStmt(Statement stmt) {
    if (stmt != null) {
      try {
        stmt.close();
      } catch (Exception e) {
        System.err.println(e.getClass().getName() + ": " + e.getMessage());
        System.exit(0);
      }
    }
  }
}
xust.demo.stu.domain.Student
public class Student{      
  /**
   * 学号
   */
  private String no;
  public String getNo(){
    return no;
  }

  public void setNo(String newValue){
    no = newValue;
  }
}
源代码
xust.demo.stu.domain.Student
package xust.demo.stu.domain;

/**
 * Class Student
 * 学生表
 * @author XUST
 * @version 1.0, 2023-04-20
 */
public class Student{


    /**
     * 学号
     */
    private String no;
    public String getNo(){
        return no;
    }

    public void setNo(String newValue){
        no = newValue;
    }
    /**
     * 姓名
     */
    private String name;
    public String getName(){
        return name;
    }

    public void setName(String newValue){
        name = newValue;
    }
    /**
     * 性别
     */
    private String gender;
    public String getGender(){
        return gender;
    }

    public void setGender(String newValue){
        gender = newValue;
    }
    /**
     * 年龄
     */
    private Integer age;
    public Integer getAge(){
        return age;
    }

    public void setAge(Integer newValue){
        age = newValue;
    }
    /**
     * 所在系
     */
    private String dept;
    public String getDept(){
        return dept;
    }

    public void setDept(String newValue){
        dept = newValue;
    }

    @Override
    public String toString() {
    return "{" + "\"no\": " + "\"" + no + "\"" + ", " + "\"name\": " + "\"" + name + "\"" + ", " + "\"gender\": " + "\"" + gender + "\"" + ", " + "\"age\": " + age + ", " + "\"dept\": " + "\"" + dept + "\"" +  "}";
    }
}
xust.demo.stu.dao.StudentDao.java
package xust.demo.stu.dao;
import xust.stu.Result;
import xust.demo.stu.domain.Student;

public interface StudentDao {
  /**
   * 初始化表
   * @return
   */
  Result init();

  /**
   * 增
   * @param o
   * @return
   */
  Result create(Student o);

  /**
   * 删
   * @param id
   * @return
   */
  Result delete(String no);

  /**
   * 改
   * @param o
   * @return
   */
  Result update(Student o);

  /**
   * 查
   * @param no
   * @return
   */
  Result get(String no);

  /**
   * 查
   * @return
   */
  Result getAll();
}
源代码
xust.demo.stu.dao.StudentDaoImpl.java
package xust.demo.stu.dao;

import java.sql.*;
import java.util.ArrayList;
import xust.stu.Result;
import xust.stu.ConnectionUtil;
import xust.demo.stu.domain.Student;

public class StudentDaoImpl implements StudentDao{
  public Result init() {
    Result res = new Result(false);

    Connection con = null;
    Statement stmt = null;
    String sql = "create table Student(" +
      "no TEXT primary key," +
      "name TEXT not null," +
      "gender TEXT," +
      "age INTEGER," +
      "dept TEXT" +
      ");";

    con = ConnectionUtil.getConnection();
    if(con != null){
      try {
        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(String.format("select count(*) from sqlite_master where type = 'table' and Upper(name) = '%s'", "Student".toUpperCase()));
        while(rs.next()){
          int count = rs.getInt(1);

          if(count == 0 && stmt.executeUpdate(sql) > 0){
            res.code = 0;
          }          
        }
      } catch (Exception e) {
        e.printStackTrace();
        res.message = e.getMessage();
      } finally {
        ConnectionUtil.closeStmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }

  /**
   * 对象填充到关系
   */
  private void toR(Student o, PreparedStatement stmt) throws Exception{
    if(o != null && stmt != null){
      String no = o.getNo();
      if(no != null){
        stmt.setString(1, no);       
      }
      String name = o.getName();
      if(name != null){
        stmt.setString(2, name);       
      }
      String gender = o.getGender();
      if(gender != null){
        stmt.setString(3, gender);       
      }
      Integer age = o.getAge();
      if(age != null){
        stmt.setInt(4, age);       
      }
      String dept = o.getDept();
      if(dept != null){
        stmt.setString(5, dept);       
      }
    }
  }

  /**
   * 关系填充到对象
   */
  private Student toO(ResultSet rs) throws Exception{
    Student res = null;

    if(rs != null){
      res = new Student();
      res.setNo(rs.getString("no"));
      res.setName(rs.getString("name"));
      res.setGender(rs.getString("gender"));
      res.setAge(rs.getInt("age"));
      res.setDept(rs.getString("dept"));
    }

    return res;
  }

  public Result create(Student o) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "insert into Student values (?, ?, ?, ?, ?)";
    con = ConnectionUtil.getConnection();
    if (o != null && con != null) {
      try {
        stmt = con.prepareStatement(sql);
        toR(o, stmt);
        if(stmt.executeUpdate() > 0){
          res.code = 0;
        }
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }
    }

    return res;
  }

  public Result delete(String no) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "delete from Student where no = ?;";
    con = ConnectionUtil.getConnection();
    if(con != null){
      try {

        stmt = con.prepareStatement(sql);
        stmt.setString(1, no);
        res.code = 0;
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }

  public Result update(Student o) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "update Student set No = ?, Name = ?, Gender = ?, Age = ?, Dept = ? where no = ?";
    con = ConnectionUtil.getConnection();
    if (o != null && con != null) {
      try {

        stmt = con.prepareStatement(sql);
        toR(o, stmt);
        stmt.setString(6, o.getNo());
        if(stmt.executeUpdate() > 0){
          res.code = 0;
        }
      } catch (Exception e) {
        e.printStackTrace();
        res.message = e.getMessage();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }
    }

    return res;
  }

  public Result get(String no) {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "select * from Student where no = ?";
    con = ConnectionUtil.getConnection();
    if(con != null){
      try {
        stmt = con.prepareStatement(sql);
        stmt.setString(1, no);
        ResultSet rs = stmt.executeQuery();
        Student last = null;
        while (rs.next()) {
          last = new Student();
          last.setNo(rs.getString("no"));
          last.setName(rs.getString("name"));
          last.setGender(rs.getString("gender"));
          last.setAge(rs.getInt("age"));
          last.setDept(rs.getString("dept"));
        }

        res.code = 0;
        res.data = last;
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }

  public Result getAll() {
    Result res = new Result(false);

    Connection con = null;
    PreparedStatement stmt = null;
    String sql = "select * from Student";
    con = ConnectionUtil.getConnection();
    if(con != null){
      try {
        stmt = con.prepareStatement(sql);
        ResultSet rs = stmt.executeQuery();
        ArrayList<Student> data = new ArrayList<Student>();
        while (rs.next()) {
          Student last = toO(rs);
          data.add(last);
        }

        res.code = 0;
        res.data = data;
      } catch (Exception e) {
        res.message = e.getMessage();
        e.printStackTrace();
      } finally {
        ConnectionUtil.closePstmt(stmt);
        ConnectionUtil.closeConnection(con);
      }      
    }

    return res;
  }
}
xust.demo.stu.dao.StudentDaoTest.java
package xust.demo.stu.dao;

import java.util.ArrayList;
import xust.stu.Result;
import xust.demo.stu.domain.Student;

public class StudentDaoTest {
  public static void main(String[] args) {
    StudentDao dao = new StudentDaoImpl();
    Result res_init = dao.init();
    System.out.println("init=" + res_init.code);

    Student o1 = new Student();
    o1.setNo("X1");
    o1.setName("X1");
    o1.setGender("X1");
    o1.setAge(1);
    o1.setDept("X1");

    Student o2 = new Student();
    o2.setNo("X2");
    o2.setName("X2");
    o2.setGender("X2");
    o2.setAge(2);
    o2.setDept("X2");
    dao.create(o2);
    Result res_create = dao.create(o1);
    System.out.println("create=" + res_create.code);

    Result res_update = dao.update(o1);
    System.out.println("update=" + res_update.code);

    Result res_delete = dao.delete("X1");
    System.out.println("delete=" + res_delete.code);

    Result res_get = dao.get("X2");

    Result res_getAll = dao.getAll();
    if(res_getAll.code == 0){
      for(Student o: (ArrayList<Student>)res_getAll.data){
        System.out.println(o.toString());
      }
    }
  }
}
DaoTest/StudentDaoTest.bat
1
2
3
4
5
6
7
8
del stu.db
javac -encoding utf-8 xust/stu/Result.java -d .
javac -encoding utf-8 xust/stu/ConnectionUtil.java -d .
javac -encoding utf-8 xust/stu/demo/domain/Student.java -d .
javac -encoding utf-8 xust/stu/demo/dao/StudentDao.java -d .
javac -encoding utf-8 xust/stu/demo/dao/StudentDaoImpl.java -d .
javac -encoding utf-8 xust/stu/demo/dao/StudentDaoTest.java -d .
java -classpath ".;sqlite-jdbc-3.41.0.0.jar" xust.stu.demo.dao.StudentDaoTest > StudentDaoTestResult.txt
运行结果
1
2
3
4
5
6
init=1
create=0
update=0
delete=0
{"no": "X2", "name": "X2", "gender": "X2", "age": 2, "dept": "X2"}
{"no": "X1", "name": "X1", "gender": "X1", "age": 1, "dept": "X1"}